#ifndef _BAC_INET_SOCKET_H_
#define _BAC_INET_SOCKET_H_

#include <limits.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <thread>

#include <sys/socket.h>
#include <netinet/in.h>

#define SOCKIDTYPE int

#define MAX_CMD_LEN (1024)

#define MAX_B_CMD_LISTEN_CLIENT_Fd_NUM (255)
#define MAX_BUFF_SIZE (1024 * 1024 * 16)

#define ERROR_SOCKET_CLOSED (-1035)

#ifdef __ANDROID__
#include <android/log.h>
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,  "BCMB_SOCK", __VA_ARGS__)
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, "BCMB_SOCK", __VA_ARGS__)
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN,  "BCMB_SOCK", __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, "BCMB_SOCK", __VA_ARGS__)
#else
#define LOGI(str, ...) do{printf("BCMB_SOCK ");printf(str,##__VA_ARGS__);printf("\n");}while(0)
#define LOGD(str, ...) do{printf("BCMB_SOCK ");printf(str,##__VA_ARGS__);printf("\n");}while(0)
#define LOGW(str, ...) do{printf("BCMB_SOCK ");printf(str,##__VA_ARGS__);printf("\n");}while(0)
#define LOGE(str, ...) do{printf("BCMB_SOCK ");printf(str,##__VA_ARGS__);printf("\n");}while(0)
#endif

typedef int (*CommandProcessorFuncType)(const char * cmdStr, char* const response, int);

typedef struct {
    void* pThis;
    CommandProcessorFuncType handler;
    int socketFd;
    
} threadArgType;

namespace com {
namespace fiill {

class BacInetSocket {
public: 
    int isExiting;
    virtual ~BacInetSocket();
    BacInetSocket(SOCKIDTYPE id);
    //get socket fd
    int get_service_fd() { return serverFd;}

static int send_data(int fd, const char * buffer, int max_len);
static int receive_data(int fd, const char * buffer, int max_len);

protected:
    virtual int processing() = 0;
    int serverFd;  //server socket FD
    const SOCKIDTYPE mId;

private:
    BacInetSocket() = delete;
};

class BacInetSocketServer : public BacInetSocket {
public:
    BacInetSocketServer(SOCKIDTYPE id, CommandProcessorFuncType handler, int mode);
    ~BacInetSocketServer(){}
    int start_process(){return processing();}
    int exec_send_once(int clientFd, CommandProcessorFuncType handler);

    int service_listen();
    int getFlag(){return mDefaultFlag;}

protected:
    virtual int processing();
    const CommandProcessorFuncType mHandler;
    const int mDefaultFlag;
    
private:
    BacInetSocketServer() = delete;
};

class BacInetSocketClient : public BacInetSocket {
public:
    //connect to server
    int connect_server(const char * path);

protected:
    int clientFd;
};

} //namespace fiill
} //namespace com
#endif

